#pragma comment(lib, "opengl32")
#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "glfw3.lib")
#pragma comment(lib, "freeglut.lib")


#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <gl/glut.h>
#include <iostream>


bool    keys[1024];
GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;

double cameraX = 0.0;
double cameraY = 0.0;
double cameraZ = -5.0;

// Ambient
float ambientStrength = 0.1f;
vec3 ambient = ambientStrength * lightColor;

// Diffuse 
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;

// Specular
float specularStrength = 0.5f;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;

vec3 result = (ambient + diffuse + specular) * objectColor;
color = vec4(result, 1.0f);

GLfloat objectColorAmbient[] = { 1.0f, 0.5f, 0.31f, 1.0f };
GLfloat objectColorDiffuse[] = { 0.0f, 0.0f, 0.0f, 1.0f };
GLfloat objectColorSpecular[] = {};

GLfloat lightColorAmbient[] = { 1.0f, 0.5f, 1.0f, 1.0f };
GLfloat lightColorDiffuse[] = { 0, 0, 0, 1 };
GLfloat lightPos[] = { 1.2f, 1.0f, 2.0f, 1.0f };


void drawCube()
{
	// Draw six quads
	glBegin(GL_QUADS);

	// Front Face
	glNormal3f(0.0, 0.0, 1.0);
	glVertex3f(0.5f, 0.5f, 0.5f);
	glVertex3f(0.5f, -0.5f, 0.5f);
	glVertex3f(-0.5f, -0.5f, 0.5f);
	glVertex3f(-0.5f, 0.5f, 0.5f);


	// Back Face
	glNormal3f(0.0, 0.0, -1.0);
	glVertex3f(0.5f, 0.5f, -0.5f);
	glVertex3f(0.5f, -0.5f, -0.5f);
	glVertex3f(-0.5f, -0.5f, -0.5f);
	glVertex3f(-0.5f, 0.5f, -0.5f);

	// Top Face
	glNormal3f(0.0, 1.0, 0.0);
	glVertex3f(0.5f, 0.5f, -0.5f);
	glVertex3f(0.5f, 0.5f, 0.5f);
	glVertex3f(-0.5f, 0.5f, 0.5f);
	glVertex3f(-0.5f, 0.5f, -0.5f);

	// Bottom Face
	glNormal3f(0.0, -1.0, 0.0);
	glVertex3f(0.5f, -0.5f, -0.5f);
	glVertex3f(0.5f, -0.5f, 0.5f);
	glVertex3f(-0.5f, -0.5f, 0.5f);
	glVertex3f(-0.5f, -0.5f, -0.5f);

	// Left face
	glNormal3f(-1.0, 0.0, 0.0);
	glVertex3f(0.5f, 0.5f, 0.5f);
	glVertex3f(0.5f, 0.5f, -0.5f);
	glVertex3f(0.5f, -0.5f, -0.5f);
	glVertex3f(0.5f, -0.5f, 0.5f);

	// Right face
	glNormal3f(1.0, 0.0, 0.0);
	glVertex3f(-0.5f, 0.5f, 0.5f);
	glVertex3f(-0.5f, 0.5f, -0.5f);
	glVertex3f(-0.5f, -0.5f, -0.5f);
	glVertex3f(-0.5f, -0.5f, 0.5f);
	glEnd();
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
const GLuint WIDTH = 800, HEIGHT = 600;
void do_movement();

int main()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

	GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGLLegecy", nullptr, nullptr);
	glfwMakeContextCurrent(window);

	glfwSetKeyCallback(window, key_callback);
	glewExperimental = GL_TRUE;
	glewInit();

	int width, height;
	glfwGetFramebufferSize(window, &width, &height);
	glViewport(0, 0, width, height);
	glEnable(GL_DEPTH_TEST);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, WIDTH*1.0 / HEIGHT, 0.1, 100.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glEnable(GL_LIGHTING);

	float globalAmbient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globalAmbient);

	//glLightfv(GL_LIGHT0, GL_AMBIENT, lightColorAmbient);
	//glMaterialfv(GL_FRONT, GL_AMBIENT, objectColorAmbient);
	//glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
	//glEnable(GL_LIGHT0);


	while (!glfwWindowShouldClose(window))
	{
		GLfloat currentFrame = glfwGetTime();
		deltaTime = currentFrame - lastFrame;
		lastFrame = currentFrame;

		glfwPollEvents();
		do_movement();

		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glPushMatrix();
		glLoadIdentity();
		glTranslated(cameraX, cameraY, cameraZ);

		glPushMatrix();
		glEnable(GL_LIGHTING);
		glLightfv(GL_LIGHT0, GL_AMBIENT, lightColorAmbient);
		glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColorDiffuse);
		glMaterialfv(GL_FRONT, GL_AMBIENT, objectColorAmbient);
		glMaterialfv(GL_FRONT, GL_DIFFUSE, objectColorDiffuse);
		glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
		glEnable(GL_LIGHT0);
		drawCube();
		glDisable(GL_LIGHTING);
		glPopMatrix();

		glPushMatrix();
		glTranslated(1.2f, 1.0f, 2.0f);
		glScaled(0.2, 0.2, 0.2);
		//glColor3f(1, 0.25, 0.31);
		drawCube();
		glPopMatrix();

		glPopMatrix();


		glfwSwapBuffers(window);
	}
	glfwTerminate();
	return 0;
}


void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
		glfwSetWindowShouldClose(window, GL_TRUE);
	if (key >= 0 && key < 1024)
	{
		if (action == GLFW_PRESS)
			keys[key] = true;
		else if (action == GLFW_RELEASE)
			keys[key] = false;
	}
}

void do_movement()
{
	if (keys[GLFW_KEY_W])
		cameraZ += 0.2f;
	if (keys[GLFW_KEY_S])
		cameraZ -= 0.2f;
	if (keys[GLFW_KEY_A])
		cameraX += 0.2f;
	if (keys[GLFW_KEY_D])
		cameraX -= 0.2f;
}